package com.zu.commu.remote;

import com.zu.commu.context.ServerContext;
import com.zu.commu.remote.session.Session;
import com.zu.commu.remote.session.SessionManager;
import com.zu.commu.remote.threads.ReadThreadManager;
import org.apache.log4j.Logger;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class RemoteServer {
    Logger log = Logger.getLogger(RemoteServer.class);
    private static ServerSocketChannel serverChannel;
    private static ServerSocket serverSocket;
    private static Selector selector;

    public static Selector getSelector() {
        return selector;
    }

    public void startServer() {
        try {
            serverChannel = ServerSocketChannel.open();
            serverChannel.configureBlocking(false);
            serverSocket = serverChannel.socket();
            serverSocket.bind(new InetSocketAddress(ServerContext.remotePort));
            //serverSocket.bind(new InetSocketAddress(4018));
            selector = Selector.open();
            serverChannel.register(selector, 16);
        } catch (Exception e1) {
            System.out.println("!! 启动Socket服务时出错！");
            e1.printStackTrace();
        }
        //开启读取线程
        ReadThreadManager.instance();

        System.out.println("@@ CommuServer remote—PORT : " + ServerContext.remotePort + " @@");

        ServerContext.remoteServerStarted = true;
        while (ServerContext.remoteServerStarted) {
            int numKeys = 0;
            try {
                Thread.sleep(100L);
                log.debug("采用NIO-循环等待-客户端连接过来或者发送数据过来！");
                numKeys = selector.select();
                //如果有新的连接或数据过来
                log.debug("----------新的连接过来------------");
                if (numKeys > 0) {
                    //把所有的key读出来
                    Set<SelectionKey> readyKeys = selector.selectedKeys();
                    //遍历所有的key，看是新的连接，还是旧的连接来发数据
                    for (Iterator<SelectionKey> ite = readyKeys.iterator(); ite.hasNext(); ) {
                        SelectionKey oneKey = ite.next();
                        ite.remove();
                        try {
                            //如果是新的连接握手
                            if (oneKey.isAcceptable()) {
                            	log.debug("新的连接过是来请求建立连接的！没有动作。。");
                                try {
                                    //得到服务通道
                                    ServerSocketChannel server = (ServerSocketChannel) oneKey.channel();
                                    //从服务通道得到服务
                                    SocketChannel channel = server.accept();
                                    channel.socket().setTcpNoDelay(true);
                                    channel.configureBlocking(false);
                                    //将连接注册到selector
                                    channel.register(selector, 1);
                                } catch (IOException e2) {
                                    e2.printStackTrace();
                                }

                            } else if (oneKey.isReadable()) {//如果是数据来了
                            	log.debug("不是新的连接，是来发送数据的！");
                                SocketChannel remote = (SocketChannel) oneKey.channel();
                                //从以SocketChannel连接池里面，有没有这个Session
                                Session se = SessionManager.instance().getSessionByChannel(remote);
                                if (se == null) {//线程池中还没有这个Session
                                	log.debug("Session池中【还没有】这个Session，将在下一步的HandleGprs类来处理上线，如果是上线数据的话就在下一步加入了SessionManager中！");
                                    se = new Session(remote);//创建一个新的Session
                                    //虽然没有但并不加入，因为不知道是不是我需要的链接，还没有处理上线的数据
                                    //将在下一步的HandleGprs类来处理上线，如果是上线数据的话就在下一步加入了
                                }else{
                                	log.debug("不是新的连接，是来发送数据的！，线程池中【已经有】这个Session："+se);
                                }
                                //并开始读取这个Session的数据
                            	log.debug("==============开始读取这个Session的数据===============");
                                ReadThreadManager.instance().readSocketChannel(se);
                            }else if(oneKey.isValid()){
                            	
                            	log.debug("==============连接已中断===============");
                            }

                        } catch (Exception ex) {
                            ex.printStackTrace();
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }finally{
            	log.debug("----------连接处理结束------------");
            }
        }
    }
}